//Program by:
//Ben Schmidt - bjs778 - 11054018
//Mike Nimeck - mfn028 - 11053045
//Jeff Huang - jlh105 - 11050226
//
//Fully implemented by hand, but OpenGL SuperBible example
//used heavily as reference

//includes
#include <stdlib.h>
#include <time.h>

#include <GLTools.h>
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <StopWatch.h>
#include <GL/glut.h>


#include "main.h"
#include "gravity.h"

bool gravity_center_toggle = false;

//initialize the gravity particle system
void initGravity()
{    
	GRAVITY_CENTER[0] = 800.0f;
	GRAVITY_CENTER[1] = 600.0f;
	GRAVITY_CENTER[2] = 0.0f;
	
	init_positions();
	
	init_velocity();
 
	init_mass();


}

//initialize gravity velocities
void init_velocity()
{
	float* positions = new float[GRAVITY_PARTICLES * 3];

	//initialize velocities
	init_particles_gravity(positions, 
		GRAVITY_PARTICLES, MAX_INITIAL_GRAVITY_SPEED, NULL);
	
	glBindBuffer(GL_ARRAY_BUFFER, particle_velocity[0]);
	glBufferData(GL_ARRAY_BUFFER, 
		GRAVITY_PARTICLES * 3 * sizeof(float), 
		positions, 
		GL_DYNAMIC_COPY);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
	glEnableVertexAttribArray(1);	
	
	delete[] positions;
}

//initialize gravity positions
void init_positions()
{
	float* positions = new float[GRAVITY_PARTICLES * 3];
		
	init_particles_gravity(positions, 
				GRAVITY_PARTICLES, 
				GRAVITY_SCALE, 
				GRAVITY_CENTER); 
	
	//set up position for vao
	glBindVertexArray(update_vao[0]);
	glBindBuffer(GL_ARRAY_BUFFER, particle_position[0]);
	glBufferData(
		GL_ARRAY_BUFFER,
		GRAVITY_PARTICLES * 3 * sizeof(float), 
		positions, 
		GL_DYNAMIC_COPY);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
	glEnableVertexAttribArray(0);	
	
	delete[] positions;
}

//generate masses
void init_mass()
{
    float masses[GRAVITY_PARTICLES * 3];
    float current_mass = random_float() * MASS_RANGE;
    
    for (int i = 0; i < GRAVITY_PARTICLES * 3; i++)
    {
	    float current_mass = random_float() * MASS_RANGE;
	    masses[i] = random_float() * MASS_RANGE;
	    //printf("{%d:%f}\n", i, masses[i]);
    }
    
    
    glBindBuffer(GL_ARRAY_BUFFER, particle_mass[0]);
    glBufferData(
	    GL_ARRAY_BUFFER, 
	    GRAVITY_PARTICLES * sizeof(float) * 3, 
	    masses, 
	    GL_DYNAMIC_COPY);
    
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(2);
}

//generate initial positions and velocities
void init_particles_gravity(float* positions, 
		    unsigned int num_positions, 
		    float scale, 
		    const float *bias)
{
    
    int i;
    float* p = positions;
    
    //NOTE: *p++ uses *p for the expression, 
    // then updates p to the next element.
    if (bias){
	for (i = 0; i < num_positions; i++){
	    *p++ = ((random_float() * 2) - 1) * scale;
	    *p++ = ((random_float() * 2) - 1) * scale;
	    *p++ = ((random_float() * 2) - 1) * scale;
	}
    }
    else{
	for (i = 0; i < num_positions; i++){
	    *p++ = ((random_float() * 2) - 1) * scale;
	    *p++ = ((random_float() * 2) - 1) * scale;
	    *p++ = ((random_float() * 2) - 1) * scale;
	}
    }
}

void init_particles_colour(float* colour, unsigned int num_positions)
{
        float* p = colour;

        for (int i = 0; i < num_positions; i++)
        {
            *p++ = 1.0f;
            *p++ = 0.0f;
            *p++ = 0.0f;
        }
}

void gravityMouseAction(int button, int state, int x, int y)
{  

}

// default idle gravity goal
void update_idle_gravity(float goal_position[], float time){

}


//updates the goal position
void update_gravity_goal(float goal_position[], float time){
    
}
